/**
 * @file market_data_publisher.cpp
 * @brief 市场数据发布器实现
 * @details 实现了市场数据发布器的功能，包括构造函数和主运行循环
 */

#include "market_data_publisher.h"

namespace Exchange {
  /**
   * @namespace Exchange
   * @brief 交易所相关功能的命名空间
   */
  /**
   * @brief 市场数据发布器的构造函数
   * @param market_updates 匹配引擎产生的市场数据更新队列
   * @param iface 网络接口名称
   * @param snapshot_ip 快照数据多播IP地址
   * @param snapshot_port 快照数据多播端口
   * @param incremental_ip 增量数据多播IP地址
   * @param incremental_port 增量数据多播端口
   */
  MarketDataPublisher::MarketDataPublisher(MEMarketUpdateLFQueue *market_updates, const std::string &iface,
                                           const std::string &snapshot_ip, int snapshot_port,
                                           const std::string &incremental_ip, int incremental_port)
      : outgoing_md_updates_(market_updates), snapshot_md_updates_(ME_MAX_MARKET_UPDATES),
        run_(false), logger_("exchange_market_data_publisher.log"), incremental_socket_(logger_) {
    // 初始化增量数据多播套接字
    ASSERT(incremental_socket_.init(incremental_ip, iface, incremental_port, /*is_listening*/ false) >= 0,
           "Unable to create incremental mcast socket. error:" + std::string(std::strerror(errno)));
    // 创建快照合成器
    snapshot_synthesizer_ = new SnapshotSynthesizer(&snapshot_md_updates_, iface, snapshot_ip, snapshot_port);
  }

  /**
   * @brief 主线程运行函数
   * @details 从匹配引擎的无锁队列中消费市场数据更新，将其发布到增量多播流，并转发给快照合成器
   */
  auto MarketDataPublisher::run() noexcept -> void {
    // 记录线程启动日志
    logger_.log("%:% %() %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_));
    // 主循环，当run_为true时持续运行
    while (run_) {
      // 遍历匹配引擎发送的所有市场数据更新
      for (auto market_update = outgoing_md_updates_->getNextToRead();
           outgoing_md_updates_->size() && market_update; market_update = outgoing_md_updates_->getNextToRead()) {
        // 测量从无锁队列读取的时间
        TTT_MEASURE(T5_MarketDataPublisher_LFQueue_read, logger_);

        // 记录发送的市场数据更新日志
        logger_.log("%:% %() % Sending seq:% %\n", __FILE__, __LINE__, __FUNCTION__, Common::getCurrentTimeStr(&time_str_), next_inc_seq_num_,
                    market_update->toString().c_str());

        // 测量多播发送时间并发送序列号和市场数据更新
        START_MEASURE(Exchange_McastSocket_send);
        // 首先发送序列号
        incremental_socket_.send(&next_inc_seq_num_, sizeof(next_inc_seq_num_));
        // 然后发送市场数据更新
        incremental_socket_.send(market_update, sizeof(MEMarketUpdate));
        END_MEASURE(Exchange_McastSocket_send, logger_);

        // 更新读取索引，表示已处理完毕当前市场数据更新
        outgoing_md_updates_->updateReadIndex();
        // 测量UDP写入时间
        TTT_MEASURE(T6_MarketDataPublisher_UDP_write, logger_);

        // 将该增量市场数据更新转发给快照合成器
        auto next_write = snapshot_md_updates_.getNextToWriteTo();
        // 设置序列号
        next_write->seq_num_ = next_inc_seq_num_;
        // 复制市场数据更新
        next_write->me_market_update_ = *market_update;
        // 更新写入索引
        snapshot_md_updates_.updateWriteIndex();

        // 增加序列号，为下一个市场数据更新做准备
        ++next_inc_seq_num_;
      }

      // 发布到多播流并处理可能的接收数据
      incremental_socket_.sendAndRecv();
    }
  }
}
